package com.ffcs.crmd.tsp.core.netty.client;

import java.net.SocketAddress;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ffcs.crmd.tsp.api.netty.INettyRemotingClient;
import com.ffcs.crmd.tsp.common.constant.LoggerName;
import com.ffcs.crmd.tsp.core.util.RemotingUtil;

import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

/**
 * 
 * 功能说明:通信客户端链接处理类
 *
 * @author zhongfuhua
 * 
 * @Date 2016年1月16日 下午9:41:50
 *
 *
 * 版本号  |   作者   |  修改时间   |   修改内容
 *
 */
public class NettyConnetManageHandler extends ChannelDuplexHandler {
    
    /**
     * 日志
     */
    private Logger               log = LoggerFactory.getLogger(LoggerName.RemotingLoggerName);
    
    /**
     * 通信客户端
     */
    private INettyRemotingClient remotingClient;
    
    public NettyConnetManageHandler(INettyRemotingClient nettyRemotingClient) {
        this.remotingClient = nettyRemotingClient;
    }
    
    /**
     * 
     * 功能说明:触发连接时调用
     * 
     * @author zhongfuhua
     *
     * @Date 2016年1月16日
     *
     */
    @Override
    public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise future) throws Exception {
        log.info("NETTY PIPELINE: one channel{} connect", ctx.channel());
        super.connect(ctx, remoteAddress, localAddress, future);
    }
    
    /**
     * 
     * 功能说明:断开连接时调用
     * 
     * @author zhongfuhua
     *
     * @Date 2016年1月16日
     *
     */
    @Override
    public void disconnect(ChannelHandlerContext ctx, ChannelPromise future) throws Exception {
        log.info("NETTY PIPELINE: one channel{} disconnect", ctx.channel());
        remotingClient.closeChannel(RemotingUtil.parseChannelRemote(ctx.channel()), ctx.channel());
        super.disconnect(ctx, future);
    }
    
    /**
     * 
     * 功能说明:关闭连接时调用
     * 
     * @author zhongfuhua
     *
     * @Date 2016年1月16日
     *
     */
    @Override
    public void close(ChannelHandlerContext ctx, ChannelPromise future) throws Exception {
        log.info("NETTY PIPELINE: one channel{} close", ctx.channel());
        remotingClient.closeChannel(RemotingUtil.parseChannelRemote(ctx.channel()), ctx.channel());
        super.close(ctx, future);
    }
    
    /**
     * 
     * 功能说明:通道通信异常时调用
     * 
     * @author zhongfuhua
     *
     * @Date 2016年1月16日
     *
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.warn("NETTY PIPELINE: one channel{} occur exception:", ctx.channel(), cause);
        remotingClient.closeChannel(RemotingUtil.parseChannelRemote(ctx.channel()), ctx.channel());
        super.exceptionCaught(ctx, cause);
    }
    
    /**
     * 
     * 功能说明:用户事件触发时调用
     * 
     * @author zhongfuhua
     *
     * @Date 2016年1月16日
     *
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent evnet = (IdleStateEvent) evt;
            if (evnet.state().equals(IdleState.ALL_IDLE)) {
                log.warn("NETTY PIPELINE: channel{} occur a idle event:{}", ctx.channel(), evnet);
                remotingClient.closeChannel(RemotingUtil.parseChannelRemote(ctx.channel()), ctx.channel());
            }
        }
        ctx.fireUserEventTriggered(evt);
    }
    
}
